//
// Created by korack on 25-5-25.
//

#include "VBattery.h"

#include "Serial.h"
#include "Tools.h"

struct _VBattery
{
        Serial                 parent_instance;
        void                  *object;
        VBatteryMessageHandler handler;
        uint16_t               quantity;
        uint16_t               charge_voltage;
        uint16_t               amper;
};

static bool     is_inited = false;
static VBattery global_vbattery;

static void
vbattery_serial_handler_cb(VBattery *self, const uint8_t *datas)
{
        uint8_t status = 0;

        self->quantity = 0;
retry:
        switch (status) {
        case 0:
                if (*datas == ',') {
                        status = 1;
                        datas += 1;
                        self->charge_voltage = 0;
                        break;
                }
                self->quantity = self->quantity * 10 + (*datas++ - '0');
                if (self->quantity > 10000)
                        self->quantity = 10000;
                break;
        case 1:
                if (*datas == ',') {
                        status = 2;
                        datas += 1;
                        self->amper = 0;
                        break;
                }
                self->charge_voltage =
                        self->charge_voltage * 10 + (*datas++ - '0');
                break;
        case 2:
                if (*datas == '\0') {
                        if (self->handler && self->object) {
                                self->handler(self->object,
                                              self->quantity,
                                              self->charge_voltage,
                                              self->amper);
                        }
                        return;
                }
                self->amper = self->amper * 10 + (*datas++ - '0');
                break;
        default:
                break;
        }

        goto retry;
}

VBattery *
vbattery_new_from_global(void)
{
        if (is_inited)
                return &global_vbattery;

        serial_init(SERIAL(&global_vbattery),
                    SERIAL_TYPE_USART1,
                    SERIAL_IRQ_HANDLER(vbattery_serial_handler_cb));

        global_vbattery.charge_voltage = 0;
        global_vbattery.amper          = 0;
        global_vbattery.quantity       = 0;
        global_vbattery.handler        = NULL;

        is_inited                      = true;
        return &global_vbattery;
}

void
vbattery_connect_message_handler(VBattery                    *self,
                                 void                        *object,
                                 const VBatteryMessageHandler handler)
{
        self->object  = object;
        self->handler = handler;
}

float
vbattery_get_charge_percent(const VBattery *self)
{
        return (float)self->quantity / 10000.0f;
}

float
vbattery_get_charge_voltage(const VBattery *self)
{
        return (float)self->charge_voltage / 10.0f;
}

float
vbattery_get_amper(const VBattery *self)
{
        return self->amper;
}

void
vbattery_set_duty_cycle(VBattery *self, const uint16_t duty_cycle)
{
        char buffer[16];
        sprintf_b(buffer, "%u\r\n", duty_cycle);
        serial_send_text(SERIAL(self), buffer);
}
